using Universal.Application.Repositories;
using Universal.Domain.Entities.App;
using Microsoft.EntityFrameworkCore;
using Universal.Domain.Repositories;
using Universal.Application.Contracts.Common;
using Universal.Application.Contracts.Dto.Role;
using System.Data.Common;
using Microsoft.VisualBasic;
using Universal.Application.Contracts.Dto;
namespace Universal.Application.Services;

/// <summary>
/// 角色服务
/// </summary>
public class RoleService : IRoleService
{
    private readonly IRepository<AppRole> _roleRep;
    private readonly IRepository<AppPermission> _permissionRep;
    private readonly IRepository<AppUser> _userRep;
    private readonly IRepository<AppMenu> _menuRep;
    private readonly ILogService _logService;

    public RoleService(IRepository<AppMenu> menuRep, ILogService logService, IRepository<AppRole> roleRep, IRepository<AppPermission> permissionRep, IRepository<AppUser> userRep)
    {
        _roleRep = roleRep;
        _permissionRep = permissionRep;
        _userRep = userRep;
        _menuRep = menuRep;
        _logService = logService;
    }

    public async Task<dynamic> UpdateRoleAsync(Guid id, UpdateRoleDto updateRoleDto)
    {
        var role = await _roleRep.GetByIdAsync(id);
        if (role == null)
        {
            return ApiResponse<string>.Failure(5001, "角色不存在，请确认后重试！！");
        }

        role.IsActive = updateRoleDto.IsActive;
        role.Rolename = updateRoleDto.Rolename;
        role.Description = updateRoleDto.Description;
        role.IsDefault = updateRoleDto.IsDefault;

        await _roleRep.UpdateAsync(role);
        await _logService.WriteLogAsync($"角色{role.Rolename}更新成功");
        return ApiResponse<string>.Success("更新角色基本信息成功");

    }

    // 分配菜单
    public async Task<dynamic> AssignMenusAsync(Guid roleId, AssignMenusDto assignMenusDto)
    {
        var role = await _roleRep.GetByIdWithIncludesAsync(roleId, r => r.Menus);

        if (role == null)
        {
            return ApiResponse<string>.Failure(5001, "分配菜单失败，角色不存在，请确认后重试！！");
        }

        // 获取所有要分配的菜单
        var menus = await _menuRep.Query()
            .Where(m => assignMenusDto.MenuIds.Contains(m.Id))
            .ToListAsync();

        // 分配菜单（覆盖式）
        role.AssignMenus(menus);

        await _roleRep.UpdateAsync(role);
        await _logService.WriteLogAsync($"角色{role.Rolename}分配菜单成功");

        return ApiResponse<string>.Success("分配菜单成功");

    }

    // 分配权限
    public async Task<dynamic> AssignPermissionsAsync(Guid roleId, AssignPermissionsDto assignPermissionsDto)
    {
        var role = await _roleRep.GetByIdWithIncludesAsync(roleId, r => r.Permissions);

        if (role == null)
        {
            return ApiResponse<string>.Failure(5001, "分配权限失败，角色不存在，请确认后重试！！");
        }

        // 清空所有权限
        role.Permissions.Clear();

        if (assignPermissionsDto.PermissionIds != null)
        {
            foreach (var permissionId in assignPermissionsDto.PermissionIds)
            {
                var permission = await _permissionRep.GetByIdAsync(permissionId);
                if (permission != null)
                {
                    role.AssignPermission(permission);
                }
            }
        }

        await _roleRep.UpdateAsync(role);
        await _logService.WriteLogAsync($"角色{role.Rolename}分配权限成功");
        return ApiResponse<string>.Success("分配权限成功");

    }

    // 创建角色
    public async Task<dynamic> CreateRoleAsync(CreateRoleDto createRoleDto)
    {
        // 角色名唯一校验
        var Roles = await _roleRep.GetAllAsync();

        var exists = Roles.Any(r => r.Rolename == createRoleDto.Rolename);

        if (exists)
        {
            return ApiResponse<string>.Failure(5001, "角色已存在，请确认后重试！！");
        }

        var Role = new AppRole
        {
            Rolename = createRoleDto.Rolename,
            Description = createRoleDto.Description,
            IsActive = createRoleDto.IsActive,
            IsDefault = createRoleDto.IsDefault
        };

        await _roleRep.AddAsync(Role);
        await _logService.WriteLogAsync($"角色{Role.Rolename}创建成功");

        return ApiResponse<string>.Success("创建角色成功");

    }

    // 获取单个角色基本信息
    public async Task<dynamic> GetRoleByIdAsync(Guid id)
{
    // 包含菜单和权限
    var role = await _roleRep.Query()
        .Include(r => r.Menus)
        .Include(r => r.Permissions)
        .FirstOrDefaultAsync(r => r.Id == id);

    if (role == null)
    {
        return ApiResponse<string>.Failure(5001, "角色不存在，请确认后重试！！");
    }

    // 构建菜单DTO
    var menuDtos = role.Menus?.Select(m => new RoleViewMenuDto(
        Id: m.Id,
        Menuname: m.Menuname,
        Path: m.Path,
        Icon: m.Icon,
        Sort: m.Sort,
        ParentId: m.ParentId,
        Parent: null,
        Children: new List<RoleViewMenuDto>()
    )).ToList() ?? new List<RoleViewMenuDto>();

    // 构建权限DTO
    var permissionDtos = role.Permissions?.Select(p => new RoleViewPermissionDto(
        p.Id,
        p.PermissionName,
        p.IsActive
    )).ToList() ?? new List<RoleViewPermissionDto>();

        // 构建角色详情DTO
#pragma warning disable CS8601 // 引用类型赋值可能为 null。
        var roleDetailDto = new RoleDetailDto
    {
        Id = role.Id,
        Rolename = role.Rolename,
        Description = role.Description,
        IsDefault = role.IsDefault,
        IsActive = role.IsActive,
        Menus = menuDtos,
        Permissions = permissionDtos
    };
#pragma warning restore CS8601 // 引用类型赋值可能为 null。

        return ApiResponse<RoleDetailDto>.Success(roleDetailDto);
}

    public async Task<dynamic> DeleteRoleAsync(Guid roleId)
    {
        var role = await _roleRep.GetByIdWithIncludesAsync(roleId, r => r.Users);
        if (role == null)
        {
            return ApiResponse<string>.Failure(5001, "删除失败，角色不存在，请确认后重试！！");
        }

        // 超级管理员不能删除（假设超级管理员名为“超级管理员”或有特殊标识）
        if (role.Rolename == "超级管理员")
        {
            return ApiResponse<string>.Failure(5002, "超级管理员无法删除！！");
        }

        // 检查该角色下是否有用户还在使用
        if (role.Users != null && role.Users.Any())
        {
            return ApiResponse<string>.Failure(5003, $"该角色下有{role.Users.Count}个用户在使用，无法删除！！");
        }

        await _roleRep.DeleteAsync(role);
        await _logService.WriteLogAsync($"角色{role.Rolename}删除成功");
        return ApiResponse<string>.Success($"删除{role.Rolename}角色成功");
    }

    public async Task<dynamic> DisableRoleAsync(Guid id)
    {
        var Role = await _roleRep.GetByIdAsync(id);

        if (Role == null)
        {
            return ApiResponse<string>.Failure(5001, "角色不存在，请确认后重试！！");
        }

        if (Role.Rolename == "超级管理员")
        {
            return ApiResponse<string>.Failure(5002, "您无权限操作超级管理员！！");
        }

        if (Role.IsActive == false)
        {
            return ApiResponse<string>.Failure(5003, $"{Role.Rolename}角色已禁用，无需重复禁用！！");
        }

        Role.IsActive = false;
        await _roleRep.UpdateAsync(Role);
        await _logService.WriteLogAsync($"角色{Role.Rolename}禁用成功");
        return ApiResponse<string>.Success($"{Role.Rolename}角色禁用成功");

    }

    public async Task<dynamic> EnableRoleAsync(Guid id)
    {
        var Role = await _roleRep.GetByIdAsync(id);

        if (Role == null)
        {
            return ApiResponse<string>.Failure(5001, "角色不存在，请确认后重试！！");
        }

        if (Role.Rolename == "超级管理员")
        {
            return ApiResponse<string>.Failure(5002, "您无权限操作超级管理员！！");
        }

        if (Role.IsActive == true)
        {
            return ApiResponse<string>.Failure(5003, $"{Role.Rolename}角色已启用，无需重复启用！！");
        }

        Role.IsActive = true;
        await _roleRep.UpdateAsync(Role);
        await _logService.WriteLogAsync($"角色{Role.Rolename}启用成功");
        return ApiResponse<string>.Success($"{Role.Rolename}角色启用成功");

    }

    // 分页角色列表
    public async Task<ApiResponse<PagedResult<RoleViewDto>>> GetRolesPagedAsync(int pageIndex, int pageSize)
    {
        var (roles, totalCount) = await _roleRep.GetPagedAsync(pageIndex, pageSize, r => r.Permissions);
        var roleDtos = roles.Select(role => new RoleViewDto(
            role.Id,
            role.Rolename,
            role.Description,
            role.IsDefault,
            role.IsActive,
            role.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss"),
            role.UpdatedAt.ToString("yyyy-MM-dd HH:mm:ss"),
            role.Permissions.Select(p => new RoleViewPermissionDto(p.Id, p.PermissionName, p.IsActive))  // 添加 IsActive 字段
        ));
        var pagedResult = new PagedResult<RoleViewDto>
        {
            TotalCount = totalCount,
            TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize),
            PageIndex = pageIndex,
            PageSize = pageSize,
            Items = roleDtos.ToList()
        };
        return ApiResponse<PagedResult<RoleViewDto>>.Success(pagedResult);
    }

    //  角色界面返回所有菜单信息
    public async Task<dynamic> GetRoleViewMenuAsync()
    {
        // 获取所有菜单，包含父子关系
        var allMenus = await _menuRep.Query()
            .Include(m => m.Parent)
            .Include(m => m.Children)
            .OrderBy(m => m.Sort)
            .ToListAsync();

        // 构建菜单树
        var menuTree = BuildMenuTree(allMenus);

        return ApiResponse<List<RoleViewMenuDto>>.Success(menuTree);
    }

    // 获取角色页面中需要的所有权限
    public async Task<dynamic> GetRoleViewpermissionAsync()
    {
        var permissions = await _permissionRep.GetAllAsync();
        var permissionsDto = permissions.Select(p => new RoleViewPermissionDto(
            p.Id,
            p.PermissionName,
            p.IsActive  // 添加 IsActive 字段
        )).ToList();

        return ApiResponse<List<RoleViewPermissionDto>>.Success(permissionsDto);

    }

    // 构建菜单树的辅助方法
    private List<RoleViewMenuDto> BuildMenuTree(List<AppMenu> allMenus, Guid? parentId = null)
    {
        var tree = new List<RoleViewMenuDto>();

        var menus = allMenus.Where(m => m.ParentId == parentId).OrderBy(m => m.Sort);

        foreach (var menu in menus)
        {
            var menuDto = new RoleViewMenuDto(
                Id: menu.Id,
                Menuname: menu.Menuname,
                Path: menu.Path,
                Icon: menu.Icon,
                Sort: menu.Sort,
                ParentId: menu.ParentId,
                Parent: menu.Parent != null ? new RoleViewMenuDto(
                    Id: menu.Parent.Id,
                    Menuname: menu.Parent.Menuname,
                    Path: menu.Parent.Path,
                    Icon: menu.Parent.Icon,
                    Sort: menu.Parent.Sort,
                    ParentId: menu.Parent.ParentId,
                    Parent: null,
                    Children: new List<RoleViewMenuDto>()
                ) : null,
                Children: BuildMenuTree(allMenus, menu.Id)
            );

            tree.Add(menuDto);
        }

        return tree;
    }
}